import { messages, shallowEqual } from "share/common";
import React from "react";
import { Upload, Icon, message, Modal, Button, Row, Col, Popconfirm, Popover, Progress } from "antd";
import config from "config";
import FileViewer from "components/file-viewer";
import "styles/components/upload/index.scss";
import excelImage from "images/file-type/excel.png";
import pdfImage from "images/file-type/pdf.png";
import pptImage from "images/file-type/ppt.png";
import txtImage from "images/file-type/txt.png";
import wordImage from "images/file-type/word.png";
import unknownImage from "images/file-type/unknown.png";
import videoImage from "images/file-type/video.png";
import audioImage from "images/file-type/audio.png";
import rarImage from "images/file-type/rar.png";
import zipImage from "images/file-type/zip.png";
import ofdImage from "images/file-type/ofd.png";
import constants from "share/constants";
import Condition from "components/condition";

const { If } = Condition;

const previwAllowExtension = [
  "png",
  "gif",
  "jpg",
  "jpeg",
  "bmp",
  "doc",
  "docx",
  "ppt",
  "pptx",
  "xls",
  "xlsx",
  "txt",
  "pdf",
  "ofd",
];
const imgExtension = ["png", "gif", "jpg", "jpeg", "bmp"];
const wordExtension = ["doc", "docx"];
const videoExtension = ["mp4", "avi", "mov", "rmvb"];
const audioExtension = ["mp3"];
const rarExtension = ["rar"];
const zipExtension = ["zip"];
const pptExtension = ["ppt", "pptx"];
const excelExtension = ["xls", "xlsx"];
const txtExtension = ["txt"];
const pdfExtension = ["pdf"];
const ofdExtension = ["ofd"];

/**
 * 图片上传组件
 */
export class FileUpload extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      fileList: [],
      isExpand: true,
      previewVisible: false, // 预览控制
      previewIndex: 0, // 预览索引
      isShowExpandButton: false,
    };
    this.originFileList = [];
    this.uploadFileList = [];
    this.fileMap = {}; // 存放上传文件的列表映射
    this.fileStatusMap = {}; // 存放文件上传的状态
    this.uploadCount = 0;
    this.doneCount = 0;
  }

  componentDidMount() {
    this.initOriginFileList(this.props.defaultFileList);
  }

  componentWillReceiveProps(nextProps) {
    const { isShowDefault, defaultFileList } = this.props;
    const nextDefaultFileList = nextProps.defaultFileList;
    if (
      isShowDefault &&
      defaultFileList &&
      nextDefaultFileList &&
      !shallowEqual(defaultFileList, nextDefaultFileList)
    ) {
      this.initOriginFileList(nextProps.defaultFileList);
    }
  }

  initOriginFileList = (defaultFileList) => {
    this.originFileList = this.getOriginFileList(defaultFileList);
    this.uploadFileList = this.uploadFileList.filter((uid) => !this.originFileList.find((file) => file.uid === uid));
    this.updateFileList({
      fileList: this.originFileList,
    });
  };

  getOriginFileList = (defaultFileList) => {
    if (defaultFileList.length > 0) {
      return defaultFileList.map((file) => {
        if (!file.name) {
          file.name = file.fileName;
        }
        file.fileURL = file.fileURL || file.url;
        file.isImageType = true;
        const thumbnailUrl = file.thumbnailUrl;
        if (!thumbnailUrl) {
          file.isImageType = false;
          file.thumbnailUrl = this.getDefaultThumbImg(file);
        } else if (!thumbnailUrl.startsWith("http")) {
          file.isImageType = false;
        }
        return file;
      });
    }
    return [];
  };

  getUploadParams = () => {
    const { data, attachmentType } = this.props;
    const result = {
      attachmentType,
    };

    if (data) {
      return Object.assign(result, data);
    }
    return result;
  };

  // 图片删除
  deleteImage = (file) => {
    const { handleDelete } = this.props;
    const { uid } = file;
    handleDelete && handleDelete(file.id, file);
    const index = this.uploadFileList.indexOf(uid);
    if (index !== -1) {
      this.uploadFileList.splice(index, 1);
      delete this.fileStatusMap[uid];
      delete this.fileMap[uid];
    } else {
      const index = this.originFileList.findIndex((f) => f.attachmentOID === file.attachmentOID);
      if (index !== -1) {
        this.originFileList.splice(index, 1);
      }
    }
    this.updateFileList({ callback: this.onChange });
  };

  // 预览
  handlePreview = (file, index) => {
    console.log("handlePreview");
    const { fileList } = this.state;
    const { isPreViewCallBack, handlePreViewCallBack } = this.props;
    if (isPreViewCallBack && handlePreViewCallBack) {
      handlePreViewCallBack(file, fileList);
      return;
    }
    if (this.isAllowedFile(file) && !this.isOverSize(file)) {
      this.setState({
        previewIndex: index,
        previewVisible: true,
      });
    } else {
      this.onDownLoadFile(file);
    }
  };
  onChange = () => {
    const { fileList } = this.state;
    const { onChange } = this.props;
    onChange(fileList.filter((file) => !!(file.attachmentOID || file.id)));
  };

  updateExpandStatus() {
    setTimeout(() => {
      const { fileList } = this.state;
      const length = fileList.length;
      const dom = this.refs.container;
      const width = dom && dom.offsetWidth;
      console.log("updateExpandStatus", width, length);
      if (dom) {
        this.setState({
          isShowExpandButton: width < length * 100,
        });
      }
    }, 1);
  }

  // 更新图片列表
  updateFileList = ({ fileList, callback } = {}) => {
    let result = fileList;
    if (!result) {
      result = [].concat(this.originFileList).concat(this.uploadFileList.map((uid) => this.fileMap[uid]));
    }
    this.setState(
      {
        fileList: result,
      },
      () => {
        const { isUploading } = this.props;
        if (this.uploadCount !== this.doneCount) {
          isUploading(true);
        } else {
          isUploading(false);
        }
        this.updateExpandStatus();
        callback && callback();
      }
    );
  };

  isOverSize = (size) => {
    const { fileSize } = this.props;
    return size >= fileSize * 1024 * 1024;
  };

  isAllowedFile = (file) => {
    const extName = this.getExtName(file.name);
    return previwAllowExtension.has(extName);
  };

  getExtName = (fileName) => {
    return fileName && fileName.match(/\.([^\.]*)$/)[1];
  };

  getDefaultThumbImg = (file) => {
    const extension = this.getExtName(file.name);
    if (imgExtension.has(extension)) {
      file.isImageType = true;
      return file.thumbnailUrl || file.fileURL || unknownImage;
    }
    if (wordExtension.has(extension)) return wordImage;
    if (pptExtension.has(extension)) return pptImage;
    if (excelExtension.has(extension)) return excelImage;
    if (txtExtension.has(extension)) return txtImage;
    if (pdfExtension.has(extension)) return pdfImage;
    if (ofdExtension.has(extension)) return ofdImage;
    if (videoExtension.has(extension)) return videoImage;
    if (audioExtension.has(extension)) return audioImage;
    if (rarExtension.has(extension)) return rarImage;
    if (zipExtension.has(extension)) return zipImage;
    return unknownImage;
  };

  onProgress = (e, file) => {
    const { uid } = file;
    file.percent = e.percent;
    this.fileMap[uid] = file;
    this.updateFileList();
  };

  onBeforeUpload = (file, fileList) => {
    if (window.ISIE9) {
      //如果是 ie9 不校验
      return true;
    }
    const { uid, size } = file;
    const { maxNum, fileType, accept, fileSize } = this.props;
    if (fileType) {
      //控制上传图片的类型
      let isFileType = false;
      const acceptList = accept.split(",");
      const extName = `.${this.getExtName(file.name)}`;
      const uploadFileType = file.type;
      const realType = uploadFileType.split("/")[1];
      fileType.map((type) => {
        type = type.toLowerCase();
        if (
          uploadFileType === `image/${type}` ||
          realType === type ||
          type === extName ||
          (acceptList.includes(".ofd") && extName === ".ofd")
        ) {
          isFileType = true;
        }
      });
      if (!isFileType) {
        //上传失败，图片格式错误
        const errorMsg = messages("common-1.key1446");
        /*文件格式不正确*/
        /*上传失败，文件格式错误*/
        message.warn(`${file.name} ${errorMsg}`);
        return false;
      }
    }
    if (this.isOverSize(size)) {
      const errorMsg = messages("common-1.key1447", { arg1: fileSize });
      /*单个文件不能超过{arg1}M*/
      message.warn(errorMsg);
      return false;
    }
    if (this.originFileList.length + this.uploadFileList.length >= maxNum) {
      message.warn(`${messages("common-1.key615") /*最多上传数量*/}${maxNum}`);
      return false;
    }
    this.uploadCount++;
    this.fileMap[uid] = file;
    this.fileStatusMap[uid] = "uploading";
    this.uploadFileList.push(uid);
    this.updateFileList();
  };

  onError = (error, res, file) => {
    console.log("onError", error, res, file);
    const { uid } = file;
    const index = this.uploadFileList.indexOf(uid);
    if (index !== -1) {
      message.error(`${file.name} ${messages("common-1.key59") /*上传失败*/} ${res ? res.message : ""}`);
      this.uploadFileList.splice(index, 1);
      delete this.fileStatusMap[uid];
      delete this.fileMap[uid];
    }
    this.doneCount += 1;
    this.updateFileList({ callback: this.onChange });
  };

  onSuccess = (response, file) => {
    const { fileUrlKey, responseFilePath } = this.props;
    console.log("onSuccess", response, file);
    this.doneCount += 1;
    const { uid, name, percent, type, size } = file;
    if (responseFilePath) {
      const responseFilePathArr = responseFilePath.split(".");
      while (responseFilePathArr.length && response) {
        response = response[responseFilePathArr.shift()];
      }
    }
    let { thumbnailUrl } = response;
    file = response;
    file.uid = uid;
    file.name = name;
    file.percent = percent;
    file.type = type;
    file.size = size;
    file.isImageType = true;
    if (!file.fileURL) {
      file.fileURL = response[fileUrlKey];
    }

    if (!thumbnailUrl) {
      file.isImageType = false;
      thumbnailUrl = this.getDefaultThumbImg(file);
    }
    file.thumbnailUrl = thumbnailUrl;
    this.fileMap[uid] = file;
    this.fileStatusMap[uid] = "success";
    message.success(`${file.fileName || file.name} ${messages("common-1.key60") /*上传成功*/}`);
    this.updateFileList({ callback: this.onChange });
  };

  onDownLoadFile = (file, e) => {
    if (e) {
      e.preventDefault();
      e.stopPropagation();
    }
    window.open(file.fileURL, "_blank");
  };

  toggleFileList = () => {
    this.setState({
      isExpand: !this.state.isExpand,
    });
  };

  // 图片展开折叠按钮
  FileToggleButtons = ({ visible }) => {
    const { isExpand } = this.state;
    if (!visible) return null;
    return (
      <div className="toggle-btn-wrapper">
        <div className="toggle-btns" onClick={this.toggleFileList}>
          <If value={isExpand}>
            <div className={"btn-name btn-up"}>
              <span>{messages("common.fold") /*收起*/}</span>
              <Icon type={"up"} className={"icon icon-up"} />
            </div>
          </If>
          <If value={!isExpand}>
            <div className={"btn-name btn-down"}>
              <span>{messages("common-1.key126") /*展开*/}</span>
              <Icon type={"down"} className={"icon icon-down"} />
            </div>
          </If>
        </div>
      </div>
    );
  };

  // 图片操作按钮
  FileActionButtons = ({ visible = true, file, onDownLoadFile, deleteEnable = true, downLoadEnable = true }) => {
    if (!visible) return null;
    return (
      <div className="thumb-action-btns btns-group">
        <If value={downLoadEnable}>
          <span>
            <Icon type="download" className={"action-icon"} onClick={(e) => this.onDownLoadFile(file, e)} />
          </span>
        </If>
        <If value={deleteEnable}>
          <span>
            <Popconfirm
              title={`${messages("common-1.key63") /*确定删除该附件吗*/}？`}
              onConfirm={(e) => this.deleteImage(file)}
              okText={messages("common.ok") /*确定*/}
              cancelText={messages("common.cancel") /*取消*/}
            >
              <Icon
                type="delete"
                className="action-icon"
                onClick={(e) => {
                  e.stopPropagation();
                }}
              />
            </Popconfirm>
          </span>
        </If>
      </div>
    );
  };

  // 附件上传中
  FileItemUploading = ({ file }) => {
    return (
      <div className="file-item">
        <span className={"thumb-image-wrapper file-loading-wrapper"}>
          <span className={"upload-text"}>{messages("common-1.key1427") /*上传中*/}</span>
          <Progress percent={file.percent || 0} showInfo={false} className={"loading-progress"} />
        </span>
      </div>
    );
  };

  // 附件正常展示
  FileItemThumb = ({ file, index }) => {
    const { FileActionButtons } = this;
    const { showFileName, disabled, removable = () => true } = this.props;
    return (
      <div
        className={`file-item ${showFileName ? "" : "file-item-no-name"}`}
        onClick={() => this.handlePreview(file, index)}
      >
        <div className="thumb-image-wrapper">
          <img
            src={file.thumbnailUrl}
            alt=""
            className={this.classNames({
              "thumb-image": true,
              "image-thumb": file.isImageType,
            })}
          />
          <FileActionButtons
            file={file}
            visible
            deleteEnable={!disabled && removable(file)}
            downLoadEnable
            onDownLoadFile={() => this.onDownLoadFile(file)}
          />
        </div>
        <If value={showFileName}>
          <Popover content={file.name} placement={"topLeft"}>
            <span className={"file-name text-ellipsis"}>{file.name}</span>
          </Popover>
        </If>
      </div>
    );
  };

  // 附件列表展示
  UploadFileList = ({ fileList = [] }) => {
    const { FileItemUploading, FileItemThumb, FileToggleButtons } = this;
    if (!fileList || !fileList.length) return null;
    const { showExpandButton, showFileName } = this.props;
    const { isShowExpandButton, isExpand } = this.state;
    return (
      <div className="file-list-container">
        <div
          className={this.classNames({
            "file-list-content": true,
            "file-list-no-expand": !isExpand,
            "file-list-content-no-name": !showFileName,
          })}
        >
          {fileList.map((file, index) => {
            const { uid } = file;
            const status = this.fileStatusMap[uid];
            if (status === "uploading") {
              return <FileItemUploading key={`uploading-${file.uid || file.attachmentOID}`} file={file} />;
            }
            return <FileItemThumb key={`thumb-${file.uid || file.attachmentOID}`} file={file} index={index} />;
          })}
        </div>
        <FileToggleButtons visible={showExpandButton && isShowExpandButton} />
      </div>
    );
  };

  // 上传提示
  UploadTips = ({ visible = true, maxNum, fileSize, attachmentTypes, tip }) => {
    if (!visible) return null;
    const { showSystemTip } = this.props;
    return (
      <div className={"tips-container"}>
        <If value={showSystemTip}>
          <div className={"system-tips upload-tips"}>
            <span>
              {
                messages("common-1.key1428", {
                  arg1: maxNum,
                  arg2: fileSize,
                }) /*最多上传{arg1}个附件，单个文件不超过{arg2}M，支持上传格式*/
              }
            </span>
            <Popover className={"popover-file-accept"} content={attachmentTypes} placement={"topRight"}>
              <Icon type="info-circle-o" />
              &nbsp;&nbsp;&nbsp;
            </Popover>
          </div>
        </If>

        <If value={tip}>
          <div className={"prop-tips upload-tips"}>{tip}</div>
        </If>
      </div>
    );
  };

  // 上传按钮
  UploadButton = ({ visible = true, disabled = false }) => {
    if (!visible) return null;
    const { mode, hideUploadText } = this.props;
    if (mode === "image") {
      return (
        <div className={"upload-btn upload-image-btn"}>
          <Icon type="plus" style={{ fontSize: 32, color: "#999" }} />
          <If value={!hideUploadText}>
            <div className="ant-upload-text" style={{ marginTop: 8, color: "#666" }}>
              {messages("common.upload") /*上传*/}
            </div>
          </If>
        </div>
      );
    }
    const typeText = messages("common.attachments");
    /*附件*/
    return (
      <Button className={"upload-btn"} disabled={disabled}>
        <Icon type="paper-clip" />
        <If value={!hideUploadText}>
          {messages("common.upload") /*上传*/}
          {typeText}
        </If>
      </Button>
    );
  };

  render() {
    const { UploadButton, UploadTips, UploadFileList } = this;
    const { fileList, previewVisible, previewIndex } = this.state;
    const {
      uploadUrl,
      headers,
      disabled = false,
      readOnly,
      accept,
      multiple,
      maxNum,
      fileSize,
      className,
      placeHolder,
      attachmentTypes,
      children,
    } = this.props;
    const isOverMaxNum = fileList.length >= maxNum;
    // let [uploadHeaders, uploadUrl] = handleUploadOptions(headers, this.props.uploadUrl);
    const uploadVisible = !readOnly && !disabled && !isOverMaxNum;
    const fileListVisible = disabled && !fileList.length;
    const uploadClassName = this.classNames({
      "upload-content": true,
      "upload-content-hidden": !uploadVisible,
    });
    return (
      <div ref={"container"} className={`upload-container ${className || ""}`}>
        <Upload
          className={uploadClassName}
          disabled={disabled}
          data={this.getUploadParams()}
          multiple={multiple}
          action={uploadUrl}
          headers={headers}
          accept={accept}
          showUploadList={false}
          onProgress={this.onProgress}
          onError={this.onError}
          beforeUpload={this.onBeforeUpload}
          onSuccess={this.onSuccess}
        >
          <If value={!!children}>{children}</If>
          <If value={!children}>
            <UploadButton visible={uploadVisible} disabled={disabled || isOverMaxNum} />
          </If>
        </Upload>
        <UploadTips
          visible={uploadVisible}
          tip={placeHolder}
          maxNum={maxNum}
          fileSize={fileSize}
          attachmentTypes={attachmentTypes}
        />
        <UploadFileList fileList={fileList} />
        <FileViewer
          visible={previewVisible}
          attachments={fileList}
          defaultIndex={previewIndex}
          onCancel={() => this.setState({ previewVisible: false })}
          urlKey="fileURL"
          valueKey="attachmentOID"
        />
        <If value={fileListVisible}>-</If>
      </div>
    );
  }
}

FileUpload.propTypes = {
  mode: React.PropTypes.string, //上传按钮模式 ['file', 'image']
  uploadUrl: React.PropTypes.string, //上传URL
  attachmentType: React.PropTypes.string.isRequired, //附件类型
  attachmentTypes: React.PropTypes.string, //可上传的文件类型
  defaultFileList: React.PropTypes.array, //默认上传的文件列表
  onChange: React.PropTypes.func, //上传成功后的回调
  maxNum: React.PropTypes.number, //最大上传文件的数量
  placeHolder: React.PropTypes.string, //控件配置的提示文案
  fileType: React.PropTypes.array, //上传文件的类型
  fileSize: React.PropTypes.number, //上传文件的大小
  isShowDefault: React.PropTypes.bool, //是否要进行回显，是否一直允许从父组件接受变化的图片列表
  data: React.PropTypes.object, //上传接口的参数
  handleDelete: React.PropTypes.func, //删除附件的回调
  handlePreViewCallBack: React.PropTypes.func, //附件预览回调
  accept: React.PropTypes.string, //附件只接受选择的类型
  isShowExtraPrompt: React.PropTypes.bool, //是否展示安全配置中支持上传的附件类型文案
  isUploading: React.PropTypes.func, //附件是否正在上传中
  showSystemTip: React.PropTypes.bool, //是否显示最多上传多少图片
  showMaxNum: React.PropTypes.bool, //是否显示最多上传多少图片
  showExpandButton: React.PropTypes.bool, //是否显示展开折叠按钮
  showFileName: React.PropTypes.bool, // 是否显示文件列表名称
  disabled: React.PropTypes.bool, //是否禁用
  readOnly: React.PropTypes.bool, // 是否是只读模式
  multiple: React.PropTypes.bool, // 是否支持多选
  hideUploadText: React.PropTypes.bool, // 是否隐藏上传按钮的文字
  fileUrlKey: React.PropTypes.string, // 获取图片url的key
  responseFilePath: React.PropTypes.string, // file的path e.g : "data.body.file"
};

FileUpload.defaultProps = {
  mode: "file",
  uploadUrl: `${config.baseUrl}/api/upload/attachment`,
  defaultFileList: [],
  onChange: () => {},
  maxNum: 9,
  placeHolder: "",
  isShowDefault: false,
  disabled: false,
  showMaxNum: false,
  isPreViewCallBack: false,
  readOnly: false,
  handleDelete: () => {
    return true;
  },
  showFileName: true,
  showExpandButton: true,
  accept: constants.acceptFileTypes,
  isShowExtraPrompt: false,
  isUploading: () => {},
  attachmentTypes: "",
  multiple: true,
  fileSize: 10,
  showSystemTip: true,
  hideUploadText: false,
  fileUrlKey: "fileURL",
  responseFilePath: "",
};

// 注意
// defaultFileList里面的对象属性要有
//   attachmentOID,
//   fileName,
//   fileURL

export default FileUpload;
